package com.example.demo;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import jnr.ffi.LibraryLoader;
import jnr.ffi.Pointer;
import jnr.ffi.Runtime;
import jnr.ffi.Struct;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class BO {
    @Value("${app.sdk.entry}")
    private String libEntry;

    @Value("${app.sdk.root")
    private String libRoot;

    @Value("${app.sdk.log.level}")
    private int logLevel;

    @Value("${app.sdk.log.path}")
    private String logPath;

    private NC nc;
    private static MSGCallBackImpl callback = new MSGCallBackImpl();

    @PostConstruct
    public void start(){
        log.info(libEntry);

        nc = LibraryLoader.create(NC.class).load(libEntry);
        Runtime runtime = Runtime.getRuntime(nc);

        NC.NET_DVR_LOCAL_SDK_PATH sdkPath = new NC.NET_DVR_LOCAL_SDK_PATH(runtime);
        sdkPath.sPath.set(libRoot);

        nc.NET_DVR_SetSDKInitCfg(2, Struct.getMemory(sdkPath));
        nc.NET_DVR_Init();

        NC.NET_DVR_ALARMER alarmer = new NC.NET_DVR_ALARMER(runtime);
        log.info("回调结构体NET_DVR_ALARMER大小：" + Struct.size(alarmer));

        nc.NET_DVR_SetLogToFile(logLevel, logPath, true);

        nc.NET_DVR_SetConnectTime(8000, 0);
        nc.NET_DVR_SetReconnect(5000, false);
        callback.setRuntime(runtime);
        nc.NET_DVR_SetDVRMessageCallBack_V30(callback, null);
        
        NC.DVR_DEVICEINFO_V30 deviceInfo = new NC.DVR_DEVICEINFO_V30(runtime);
        long userId = nc.NET_DVR_Login_V30("192.168.42.242", (short)8000,  "admin", "admin12345", deviceInfo);
        log.info("UserID: " + String.valueOf(userId));
        log.info(deviceInfo.sSerialNumber.get());

        NC.NET_DVR_SETUPALARM_PARAM alermParam = new NC.NET_DVR_SETUPALARM_PARAM(runtime);
        alermParam.dwSize.set(Struct.size(alermParam));
        alermParam.byLevel.set(0);
        alermParam.byRetVQDAlarmType.set(1);
        alermParam.byRetAlarmTypeV40.set(1);
        alermParam.byFaceAlarmDetection.set(0);
        alermParam.byRetDevInfoVersion.set(1);
        alermParam.byAlarmInfoType.set(1);
        alermParam.bySupport.set(4);
        long ret = nc.NET_DVR_SetupAlarmChan_V41(userId, alermParam);
        log.info("ret: " + String.valueOf(ret));
    }

    @PreDestroy
    public void stop(){
        nc.NET_DVR_Cleanup();
    }

    public static class MSGCallBackImpl implements NC.MSGCallBack{
        private Runtime rt;
        
        public void setRuntime(@NonNull Runtime rt){
            this.rt = rt;
        }

        @Override
        public void invoke(long lCommand, Pointer pAlarmer, String pAlarmInfo, int dwBufLen, Pointer pUser) {
            log.info("command: " + String.valueOf(lCommand) + ", alarmInfo: " + pAlarmInfo);
            NC.NET_DVR_ALARMER alarmer = new NC.NET_DVR_ALARMER(rt);
            alarmer.useMemory(pAlarmer);
            log.info(alarmer.toString());
        }
            
    };
}
